//
//  SPGameManager.m
//  ShandongPoker
//
//  Created by Developer on 2025-01-08.
//  Copyright © 2025 ShandongPoker. All rights reserved.
//

#import "SPGameManager.h"
#import "SPCard.h"
#import "SPPlayer.h"
#import "SPDeck.h"
#import "SPHandEvaluator.h"
#import "../../Core/Utils/SPConstants.h"

@interface SPGameManager ()

// 私有属性
@property (nonatomic, assign, readwrite) SPGameState gameState;
@property (nonatomic, assign, readwrite) NSInteger currentPot;
@property (nonatomic, assign, readwrite) NSInteger currentRound;
@property (nonatomic, assign, readwrite) NSInteger smallBlind;
@property (nonatomic, assign, readwrite) NSInteger bigBlind;
@property (nonatomic, assign, readwrite) NSInteger currentCallAmount;
@property (nonatomic, assign, readwrite) NSInteger minRaiseAmount;
@property (nonatomic, assign, readwrite) NSInteger dealerPosition;
@property (nonatomic, assign, readwrite) NSInteger activePlayerPosition;

@property (nonatomic, strong, readwrite) NSArray<SPPlayer *> *players;
@property (nonatomic, strong, readwrite, nullable) SPPlayer *currentPlayer;
@property (nonatomic, strong, readwrite, nullable) SPPlayer *activePlayer;
@property (nonatomic, strong, readwrite) NSArray<SPPlayer *> *activePlayers;

@property (nonatomic, strong, readwrite) SPDeck *deck;
@property (nonatomic, strong, readwrite) NSArray<SPCard *> *communityCards;
@property (nonatomic, strong, readwrite) NSArray<SPCard *> *playerHoleCards;

// 内部状态
@property (nonatomic, strong) NSMutableArray<SPCard *> *mutableCommunityCards;
@property (nonatomic, strong) NSMutableArray<SPPlayer *> *mutablePlayers;
@property (nonatomic, assign) NSInteger lastRaiseAmount;
@property (nonatomic, assign) BOOL isPaused;

@end

@implementation SPGameManager

#pragma mark - 初始化方法

- (instancetype)initWithPlayerNames:(NSArray<NSString *> *)playerNames 
                       aiDifficulty:(SPAIDifficulty)aiDifficulty 
                         smallBlind:(NSInteger)smallBlind 
                           bigBlind:(NSInteger)bigBlind {
    self = [super init];
    if (self) {
        _smallBlind = smallBlind;
        _bigBlind = bigBlind;
        _currentPot = 0;
        _currentRound = 0;
        _currentCallAmount = 0;
        _minRaiseAmount = bigBlind;
        _lastRaiseAmount = 0;
        _dealerPosition = 0;
        _activePlayerPosition = 0;
        _gameState = SPGameStateIdle;
        _isPaused = NO;
        
        // 初始化牌组
        _deck = [[SPDeck alloc] init];
        
        // 初始化公共牌
        _mutableCommunityCards = [NSMutableArray array];
        _communityCards = _mutableCommunityCards;
        
        // 创建玩家
        [self createPlayersWithNames:playerNames aiDifficulty:aiDifficulty];
        
        // 设置当前玩家（第一个玩家为人类玩家）
        _currentPlayer = _players.firstObject;
    }
    return self;
}

#pragma mark - 私有方法

- (void)createPlayersWithNames:(NSArray<NSString *> *)playerNames 
                  aiDifficulty:(SPAIDifficulty)aiDifficulty {
    NSMutableArray<SPPlayer *> *mutablePlayers = [NSMutableArray array];
    
    for (NSInteger i = 0; i < playerNames.count; i++) {
        NSString *name = playerNames[i];
        SPPlayer *player;
        
        if (i == 0) {
            // 第一个玩家为人类玩家
            player = [[SPPlayer alloc] initWithName:name chips:1000];
        } else {
            // 其他玩家为AI玩家
            player = [[SPPlayer alloc] initWithName:name chips:1000 aiDifficulty:aiDifficulty];
        }
        
        player.position = i;
        [mutablePlayers addObject:player];
    }
    
    _mutablePlayers = mutablePlayers;
    _players = mutablePlayers;
    _activePlayers = mutablePlayers;
}

- (void)setGameState:(SPGameState)gameState {
    if (_gameState != gameState) {
        _gameState = gameState;
        
        // 通知代理
        if ([self.delegate respondsToSelector:@selector(gameManager:didChangeState:)]) {
            [self.delegate gameManager:self didChangeState:gameState];
        }
    }
}

- (void)updateActivePlayers {
    NSMutableArray<SPPlayer *> *activePlayers = [NSMutableArray array];
    for (SPPlayer *player in self.players) {
        if (!player.hasFolded && !player.isAllIn) {
            [activePlayers addObject:player];
        }
    }
    _activePlayers = activePlayers;
}

- (void)moveToNextActivePlayer {
    NSInteger nextPosition = (self.activePlayerPosition + 1) % self.players.count;
    
    // 找到下一个未弃牌且未全下的玩家
    while (nextPosition != self.activePlayerPosition) {
        SPPlayer *nextPlayer = self.players[nextPosition];
        if (!nextPlayer.hasFolded && !nextPlayer.isAllIn) {
            self.activePlayerPosition = nextPosition;
            self.activePlayer = nextPlayer;
            return;
        }
        nextPosition = (nextPosition + 1) % self.players.count;
    }
}

- (BOOL)isRoundComplete {
    // 检查是否所有玩家都行动完毕
    NSInteger activePlayerCount = self.activePlayers.count;
    if (activePlayerCount <= 1) return YES;
    
    // 检查是否所有玩家都下注相同金额
    NSInteger firstBet = self.activePlayers.firstObject.currentBet;
    for (SPPlayer *player in self.activePlayers) {
        if (player.currentBet != firstBet && !player.isAllIn) {
            return NO;
        }
    }
    
    return YES;
}

- (void)collectBets {
    NSInteger totalBets = 0;
    for (SPPlayer *player in self.players) {
        totalBets += player.currentBet;
        player.currentBet = 0;
    }
    self.currentPot += totalBets;
}

- (void)dealCommunityCardsForRound:(SPGameState)round {
    NSInteger cardsToDeal = 0;
    
    switch (round) {
        case SPGameStateFlop:
            cardsToDeal = 3;
            break;
        case SPGameStateTurn:
        case SPGameStateRiver:
            cardsToDeal = 1;
            break;
        default:
            return;
    }
    
    for (NSInteger i = 0; i < cardsToDeal; i++) {
        SPCard *card = [self.deck dealCard];
        if (card) {
            [self.mutableCommunityCards addObject:card];
        }
    }
    
    // 通知代理
    if ([self.delegate respondsToSelector:@selector(gameManager:didUpdateCommunityCards:round:)]) {
        [self.delegate gameManager:self didUpdateCommunityCards:self.communityCards round:round];
    }
}

- (void)determineWinner {
    SPPlayer *winner = nil;
    SPHandResult *bestHand = nil;
    NSInteger highestScore = -1;
    
    for (SPPlayer *player in self.activePlayers) {
        if (player.hasFolded) continue;
        
        // 获取玩家最佳牌型
        NSArray<SPCard *> *allCards = [player.holeCards arrayByAddingObjectsFromArray:self.communityCards];
        SPHandResult *handResult = [SPHandEvaluator evaluateFiveCardHand:allCards];
        
        if (handResult.score > highestScore) {
            highestScore = handResult.score;
            winner = player;
            bestHand = handResult;
        }
    }
    
    // 通知代理游戏结束
    if ([self.delegate respondsToSelector:@selector(gameManager:gameDidEnd:winAmount:winningHand:)]) {
        [self.delegate gameManager:self gameDidEnd:winner winAmount:self.currentPot winningHand:bestHand];
    }
    
    // 重置游戏状态
    [self resetForNewHand];
}

- (void)resetForNewHand {
    // 重置玩家状态
    for (SPPlayer *player in self.players) {
        [player clearHoleCards];
        player.hasFolded = NO;
        player.isAllIn = NO;
        player.currentBet = 0;
    }
    
    // 清空公共牌
    [self.mutableCommunityCards removeAllObjects];
    
    // 重置牌组
    [self.deck reset];
    [self.deck shuffle];
    
    // 移动庄家位置
    self.dealerPosition = (self.dealerPosition + 1) % self.players.count;
    
    // 重置游戏状态
    self.currentPot = 0;
    self.currentCallAmount = 0;
    self.minRaiseAmount = self.bigBlind;
    self.lastRaiseAmount = 0;
    
    // 更新活跃玩家
    [self updateActivePlayers];
}

#pragma mark - 公共方法

- (void)startNewGame {
    self.gameState = SPGameStateIdle;
    [self startNewHand];
}

- (void)startNewHand {
    // 重置游戏状态
    [self resetForNewHand];
    
    // 设置盲注
    NSInteger smallBlindPos = (self.dealerPosition + 1) % self.players.count;
    NSInteger bigBlindPos = (self.dealerPosition + 2) % self.players.count;
    
    SPPlayer *smallBlindPlayer = self.players[smallBlindPos];
    SPPlayer *bigBlindPlayer = self.players[bigBlindPos];
    
    [smallBlindPlayer bet:self.smallBlind];
    [bigBlindPlayer bet:self.bigBlind];
    
    self.currentPot = self.smallBlind + self.bigBlind;
    self.currentCallAmount = self.bigBlind;
    self.minRaiseAmount = self.bigBlind;
    
    // 设置第一个行动玩家（大盲注之后的玩家）
    self.activePlayerPosition = (bigBlindPos + 1) % self.players.count;
    self.activePlayer = self.players[self.activePlayerPosition];
    
    // 发手牌
    [self dealHoleCards];
    
    self.gameState = SPGameStatePreFlop;
}

- (void)dealHoleCards {
    // 给每个玩家发2张手牌
    for (NSInteger i = 0; i < 2; i++) {
        for (SPPlayer *player in self.players) {
            SPCard *card = [self.deck dealCard];
            if (card) {
                [player addHoleCard:card];
                
                // 通知代理发牌
                if ([self.delegate respondsToSelector:@selector(gameManager:didDealCards:toPlayer:)]) {
                    [self.delegate gameManager:self didDealCards:@[card] toPlayer:player];
                }
            }
        }
    }
    
    // 更新当前玩家手牌
    _playerHoleCards = self.currentPlayer.holeCards;
}

- (void)pauseGame {
    self.isPaused = YES;
}

- (void)resumeGame {
    self.isPaused = NO;
}

- (void)endGame {
    self.gameState = SPGameStateEnded;
}

#pragma mark - 玩家操作方法

- (void)playerFold {
    if (![self canPlayerPerformAction:SPPlayerActionFold]) return;
    
    self.activePlayer.hasFolded = YES;
    [self updateActivePlayers];
    
    // 通知代理
    if ([self.delegate respondsToSelector:@selector(gameManager:playerDidAct:action:amount:)]) {
        [self.delegate gameManager:self playerDidAct:self.activePlayer action:SPPlayerActionFold amount:0];
    }
    
    [self moveToNextActivePlayer];
}

- (void)playerCheck {
    if (![self canPlayerPerformAction:SPPlayerActionCheck]) return;
    
    // 通知代理
    if ([self.delegate respondsToSelector:@selector(gameManager:playerDidAct:action:amount:)]) {
        [self.delegate gameManager:self playerDidAct:self.activePlayer action:SPPlayerActionCheck amount:0];
    }
    
    [self moveToNextActivePlayer];
}

- (void)playerCall {
    if (![self canPlayerPerformAction:SPPlayerActionCall]) return;
    
    NSInteger callAmount = self.currentCallAmount - self.activePlayer.currentBet;
    [self.activePlayer bet:callAmount];
    
    // 通知代理
    if ([self.delegate respondsToSelector:@selector(gameManager:playerDidAct:action:amount:)]) {
        [self.delegate gameManager:self playerDidAct:self.activePlayer action:SPPlayerActionCall amount:callAmount];
    }
    
    [self moveToNextActivePlayer];
}

- (void)playerRaise:(NSInteger)amount {
    if (![self canPlayerPerformAction:SPPlayerActionRaise]) return;
    if (amount < self.minRaiseAmount) return;
    
    NSInteger totalBet = self.activePlayer.currentBet + amount;
    [self.activePlayer bet:amount];
    
    self.currentCallAmount = totalBet;
    self.minRaiseAmount = amount;
    self.lastRaiseAmount = amount;
    
    // 通知代理
    if ([self.delegate respondsToSelector:@selector(gameManager:playerDidAct:action:amount:)]) {
        [self.delegate gameManager:self playerDidAct:self.activePlayer action:SPPlayerActionRaise amount:amount];
    }
    
    [self moveToNextActivePlayer];
}

- (void)playerAllIn {
    if (![self canPlayerPerformAction:SPPlayerActionAllIn]) return;
    
    NSInteger allInAmount = self.activePlayer.chips;
    [self.activePlayer allIn];
    
    // 通知代理
    if ([self.delegate respondsToSelector:@selector(gameManager:playerDidAct:action:amount:)]) {
        [self.delegate gameManager:self playerDidAct:self.activePlayer action:SPPlayerActionAllIn amount:allInAmount];
    }
    
    [self moveToNextActivePlayer];
}

#pragma mark - 查询方法

- (BOOL)canPlayerPerformAction:(SPPlayerAction)action {
    if (self.isPaused || self.gameState == SPGameStateEnded) return NO;
    if (self.activePlayer.hasFolded || self.activePlayer.isAllIn) return NO;
    
    switch (action) {
        case SPPlayerActionFold:
            return YES;
        case SPPlayerActionCheck:
            return self.activePlayer.currentBet == self.currentCallAmount;
        case SPPlayerActionCall:
            return self.activePlayer.chips >= (self.currentCallAmount - self.activePlayer.currentBet);
        case SPPlayerActionRaise:
            return self.activePlayer.chips >= self.minRaiseAmount;
        case SPPlayerActionAllIn:
            return self.activePlayer.chips > 0;
        default:
            return NO;
    }
}

- (NSInteger)getCurrentCallAmount {
    return self.currentCallAmount;
}

- (NSInteger)getMinRaiseAmount {
    return self.minRaiseAmount;
}

- (NSInteger)getMaxRaiseAmount {
    return self.activePlayer.chips;
}

- (SPHandResult *)getBestHandForPlayer:(SPPlayer *)player {
    NSArray<SPCard *> *allCards = [player.holeCards arrayByAddingObjectsFromArray:self.communityCards];
    return [SPHandEvaluator evaluateFiveCardHand:allCards];
}

@end 